package com.hhj.sharding.sphere.demo.controller;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import com.hhj.sharding.sphere.demo.base.PageVO;
import com.hhj.sharding.sphere.demo.base.Result;
import com.hhj.sharding.sphere.demo.model.OrderParamVO;
import com.hhj.sharding.sphere.demo.model.entity.Complex;
import com.hhj.sharding.sphere.demo.model.entity.Order;
import com.hhj.sharding.sphere.demo.model.entity.SingleTable;
import com.hhj.sharding.sphere.demo.model.entity.User;
import com.hhj.sharding.sphere.demo.service.IComplexService;
import com.hhj.sharding.sphere.demo.service.IOrderService;
import com.hhj.sharding.sphere.demo.service.ISingleTableService;
import com.hhj.sharding.sphere.demo.service.IUserService;
import com.hhj.sharding.sphere.demo.utils.IdWorkerUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;

/**
 * 订单接口
 *
 * @Description
 * @Author HHJ
 * @Date 2022-02-28 18:28
 */
@Slf4j
@RestController
@RequestMapping(value = "/v1/order")
public class OrderController {
    @Autowired
    private IOrderService orderService;
    @Autowired
    private IUserService userService;
    @Autowired
    private IComplexService complexService;
    @Autowired
    private ISingleTableService singleTableService;

    /**
     * 测试分库分表-分页
     */
    @PostMapping("/findPage")
    public Result<PageVO> findPage(@RequestBody OrderParamVO req) {
        log.info("测试分库分表1-分页");
        return Result.success(orderService.findPage(req));
    }

    /**
     * 测试分库分表-新增
     */
    @PostMapping("/save")
    public Result<Boolean> save(@RequestBody OrderParamVO req) {
        log.info("测试分库分表1-新增");
        orderService.save(buildOrder(null, 1L + RandomUtil.randomLong(0, 10000000), 1L + RandomUtil.randomLong(0, 10000000), req.getSnowCode()));
        return Result.success(true);
    }

    /**
     * 测试分库分表 - 修改
     */
    @PostMapping("/updateById")
    public Result<Boolean> updateById(@RequestBody OrderParamVO req) {
        log.info("测试分库分表1- 修改");
        orderService.updateById(buildOrder(req.getId(), null, null, req.getSnowCode()));
        return Result.success(true);
    }

    /**
     * 测试分库分表- 删除
     */
    @PostMapping("/deleteById")
    public Result<Boolean> deleteById(@RequestBody OrderParamVO req) {
        log.info("测试分库分表1- 删除");
        orderService.removeById(req.getId());
        return Result.success(true);
    }

    /**
     * 测试广播表
     * 广播表，在所有数据库中都存在一份一模一样的表
     * 适用于数据量不大，且到时候需要用来关联查询的表，例如字典表
     */
    @PostMapping("/broadcastTables")
    public Result<Boolean> broadcastTables(@RequestBody OrderParamVO req) {
        log.info("测试广播表");
        // ID 不能使用数据库默认自增的ID不然会报错
        // org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.executor.ExecutorException: Error getting generated key or setting result to parameter object.
        // Cause: org.apache.ibatis.executor.ExecutorException: Too many keys are generated. There are only 1 target objects. You either specified a wrong 'keyProperty' or encountered a driver bug like #1523.
        // 实体类ID, 需要使用MybatisPlus的雪花算法 @TableId(value = "id", type = IdType.ASSIGN_ID)
        User user = new User();
        user.setUserName(IdUtil.fastSimpleUUID().substring(0, 4));
        user.setUserPhone("1" + RandomUtil.randomNumbers(10));
        user.setUserEmail(IdUtil.fastSimpleUUID().substring(0, 4) + "@qq.email");
        userService.save(user);
        return Result.success(true);
    }


    /**
     * 单表，指所有的分片数据源中仅唯一存在的表
     * 比如你有10个数据库，但是仅仅只有其中1个数据库里面有
     * 适用于数据量不大、无需分片，且不用进行关联查询的表
     */
    @PostMapping("/singleTable")
    public Result<Boolean> singleTable(@RequestBody OrderParamVO req) {
        log.info("测试单表");
        long id = IdWorkerUtils.getId();
        long id2 = IdWorkerUtils.getId();
        singleTableService.save(new SingleTable(null, id + "", id + ""));
        singleTableService.save(new SingleTable(null, id2 + "", id2 + ""));
        return Result.success(true);
    }


    /**
     *
     */
    @PostMapping("/complexKey")
    public Result<Boolean> complexKey(@RequestBody OrderParamVO req) {
        log.info("测试complex");
        complexService.save(new Complex(1L, 1L));
        complexService.save(new Complex(1L, 2L));
        complexService.save(new Complex(null, 1L));
        complexService.save(new Complex(null, 2L));
        return Result.success(true);
    }

    private Order buildOrder(Long id, Long userId, Long orderId, String code) {
        Order order = new Order();
        order.setId(id);
        order.setUserId(userId);
        order.setOrderId(orderId);
        if (StringUtils.isNotBlank(code)) {
            order.setSnowCode(code);
        } else {
            order.setSnowCode(IdWorkerUtils.getId() + "");
        }
        order.setCreateTime(new Date());
        return order;
    }

}
